package com.yy.yunpan.common.util;

import com.yy.yunpan.common.constant.Constants;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 文件工具类
 *
 * @author YY
 * @since 2025-10-01
 */
public class FileUtil {

    /**
     * 文件类型映射
     */
    private static final Map<String, String> FILE_TYPE_MAP = new HashMap<>();

    static {
        // 图片类型
        FILE_TYPE_MAP.put("jpg", Constants.FileType.IMAGE);
        FILE_TYPE_MAP.put("jpeg", Constants.FileType.IMAGE);
        FILE_TYPE_MAP.put("png", Constants.FileType.IMAGE);
        FILE_TYPE_MAP.put("gif", Constants.FileType.IMAGE);
        FILE_TYPE_MAP.put("bmp", Constants.FileType.IMAGE);
        FILE_TYPE_MAP.put("webp", Constants.FileType.IMAGE);
        FILE_TYPE_MAP.put("svg", Constants.FileType.IMAGE);

        // 视频类型
        FILE_TYPE_MAP.put("mp4", Constants.FileType.VIDEO);
        FILE_TYPE_MAP.put("avi", Constants.FileType.VIDEO);
        FILE_TYPE_MAP.put("mov", Constants.FileType.VIDEO);
        FILE_TYPE_MAP.put("wmv", Constants.FileType.VIDEO);
        FILE_TYPE_MAP.put("flv", Constants.FileType.VIDEO);
        FILE_TYPE_MAP.put("mkv", Constants.FileType.VIDEO);
        FILE_TYPE_MAP.put("webm", Constants.FileType.VIDEO);

        // 音频类型
        FILE_TYPE_MAP.put("mp3", Constants.FileType.AUDIO);
        FILE_TYPE_MAP.put("wav", Constants.FileType.AUDIO);
        FILE_TYPE_MAP.put("flac", Constants.FileType.AUDIO);
        FILE_TYPE_MAP.put("aac", Constants.FileType.AUDIO);
        FILE_TYPE_MAP.put("ogg", Constants.FileType.AUDIO);

        // 文档类型
        FILE_TYPE_MAP.put("pdf", Constants.FileType.DOCUMENT);
        FILE_TYPE_MAP.put("doc", Constants.FileType.DOCUMENT);
        FILE_TYPE_MAP.put("docx", Constants.FileType.DOCUMENT);
        FILE_TYPE_MAP.put("xls", Constants.FileType.DOCUMENT);
        FILE_TYPE_MAP.put("xlsx", Constants.FileType.DOCUMENT);
        FILE_TYPE_MAP.put("ppt", Constants.FileType.DOCUMENT);
        FILE_TYPE_MAP.put("pptx", Constants.FileType.DOCUMENT);
        FILE_TYPE_MAP.put("txt", Constants.FileType.DOCUMENT);
    }

    /**
     * 根据文件名获取文件扩展名
     *
     * @param fileName 文件名
     * @return 文件扩展名（小写）
     */
    public static String getFileExtension(String fileName) {
        if (StringUtils.isBlank(fileName)) {
            return "";
        }
        int lastDotIndex = fileName.lastIndexOf('.');
        if (lastDotIndex == -1 || lastDotIndex == fileName.length() - 1) {
            return "";
        }
        return fileName.substring(lastDotIndex + 1).toLowerCase();
    }

    /**
     * 根据文件名获取文件类型
     *
     * @param fileName 文件名
     * @return 文件类型
     */
    public static String getFileType(String fileName) {
        String extension = getFileExtension(fileName);
        return FILE_TYPE_MAP.getOrDefault(extension, Constants.FileType.OTHER);
    }

    /**
     * 生成唯一文件名（UUID + 原扩展名）
     *
     * @param originalFileName 原始文件名
     * @return 唯一文件名
     */
    public static String generateUniqueFileName(String originalFileName) {
        String extension = getFileExtension(originalFileName);
        String uuid = UUID.randomUUID().toString().replace("-", "");
        return StringUtils.isNotBlank(extension) ? uuid + "." + extension : uuid;
    }

    /**
     * 生成OSS对象键
     *
     * @param userId   用户ID
     * @param fileName 文件名
     * @return OSS对象键
     */
    public static String generateOssKey(Long userId, String fileName) {
        return Constants.OSS_BASE_PATH + userId + "/" + fileName;
    }

    /**
     * 格式化文件大小
     *
     * @param size 文件大小（字节）
     * @return 格式化后的文件大小
     */
    public static String formatFileSize(long size) {
        if (size < 1024) {
            return size + " B";
        } else if (size < 1024 * 1024) {
            return String.format("%.1f KB", size / 1024.0);
        } else if (size < 1024 * 1024 * 1024) {
            return String.format("%.1f MB", size / (1024.0 * 1024.0));
        } else {
            return String.format("%.1f GB", size / (1024.0 * 1024.0 * 1024.0));
        }
    }

    /**
     * 检查文件名是否有效
     *
     * @param fileName 文件名
     * @return 是否有效
     */
    public static boolean isValidFileName(String fileName) {
        if (StringUtils.isBlank(fileName)) {
            return false;
        }
        // 检查非法字符
        String illegalChars = "<>:\"/\\|?*";
        for (char c : illegalChars.toCharArray()) {
            if (fileName.indexOf(c) != -1) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断是否为图片文件
     *
     * @param fileName 文件名
     * @return 是否为图片
     */
    public static boolean isImage(String fileName) {
        return Constants.FileType.IMAGE.equals(getFileType(fileName));
    }

    /**
     * 判断是否为视频文件
     *
     * @param fileName 文件名
     * @return 是否为视频
     */
    public static boolean isVideo(String fileName) {
        return Constants.FileType.VIDEO.equals(getFileType(fileName));
    }

    /**
     * 判断是否可预览的文件
     *
     * @param fileName 文件名
     * @return 是否可预览
     */
    public static boolean isPreviewable(String fileName) {
        String fileType = getFileType(fileName);
        return Constants.FileType.IMAGE.equals(fileType) ||
               Constants.FileType.VIDEO.equals(fileType) ||
               Constants.FileType.AUDIO.equals(fileType);
    }
}